#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "my_sys.h"

#include "gd32f450i_eval.h"
#include "lvgl.h"
#include "lv_examples/lv_exc_screen/exc_screen.h"
#include "touch_xpt2046.h"


uint8_t g_ringBuffer[150];
static int adc_counter=0;

void PRINTF_UART0(char *data)
{
	int i;
	for(i=0;i<strlen(data);i++){
		usart_data_transmit(USART0, data[i]);
		while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
	}
}
void PRINTF_UART0Len(char *data, uint32_t len)
{
	int i;
	for(i=0;i<len;i++){
		usart_data_transmit(USART0, data[i]);
		while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
	}
}

int16_t TabH[] = { //CRC 高位字节值表
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
		0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
		0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
		0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
		0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
		0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
		0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
		0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
		0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
		0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
		0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
		0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
		0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
		0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
		0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
		0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
		0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
uint16_t TabL[] = { //CRC 低位字节值表
		0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
		0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
		0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
		0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
		0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
		0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
		0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
		0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
		0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
		0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
		0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
		0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
		0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
		0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
		0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
		0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
		0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
		0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
		0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
		0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
		0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
		0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
		0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
		0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
		0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
		0x43, 0x83, 0x41, 0x81, 0x80, 0x40
} ;


uint16_t GetCRC16(uint8_t *ptr, uint8_t len)
{
	uint16_t index;
	uint8_t crch = 0xFF; //高 CRC 字节
	uint8_t crcl = 0xFF; //低 CRC 字节

	while (len--) //计算指定长度的 CRC
	{
		index = crch ^ *ptr++;
		crch = crcl ^ TabH[index];
		crcl = TabL[index];
	}
	return ((crch<<8) | crcl);
}


void adc_config(void)
{
    // enable GPIOA clock 
    // rcu_periph_clock_enable(RCU_GPIOC);
    rcu_periph_clock_enable(RCU_GPIOA);
    // enable ADC clock 
    rcu_periph_clock_enable(RCU_ADC0);
    // enable DMA clock 
    // rcu_periph_clock_enable(RCU_DMA1);  
    // config ADC clock 
    adc_clock_config(ADC_ADCCK_PCLK2_DIV6);

    
    // config the GPIO as analog mode, for ADC 
    // gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_3);
    gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_4);

    // reset ADC 
    adc_deinit();
    // ADC mode config 
    adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);
    // ADC data alignment config 
    adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);
    // ADC contineous function enable 
    adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);
    
    // ADC channel length config 
    adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 1);
    // ADC regular channel config 
    // adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_13, ADC_SAMPLETIME_480);
    adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_4, ADC_SAMPLETIME_480);
    // ADC trigger config 
    // adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_EXTI_11);
    // adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);
    
    // ADC discontinuous mode 
    // adc_discontinuous_mode_config(ADC0, ADC_REGULAR_CHANNEL, 3);

    //ADC INT
    adc_interrupt_enable(ADC0, ADC_INT_EOC);
    // adc_interrupt_enable(ADC0, ADC_INT_ROVF);
    nvic_irq_enable(ADC_IRQn, 2U, 0U);

    // ADC DMA function enable 
    // adc_dma_request_after_last_enable(ADC0);
    // adc_dma_mode_enable(ADC0);

    // enable ADC interface 
    adc_enable(ADC0);
    // wait for ADC stability 
    delay_ms(1);
    // ADC calibration and reset calibration 
    adc_calibration_enable(ADC0);
}

void timer1_config(void)
{
    rcu_periph_clock_enable(RCU_TIMER1);
    timer_oc_parameter_struct timer_ocintpara;
    timer_parameter_struct timer_initpara;

    /* TIMER1 configuration */
    timer_initpara.prescaler         = 9999;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 9999;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER1,&timer_initpara);

    timer_interrupt_enable(TIMER1, TIMER_INT_UP);
    nvic_irq_enable(TIMER1_IRQn, 1U, 0U);
    /* enable TIMER1 */
    timer_enable(TIMER1);
}

void timer2_config(void)
{
    rcu_periph_clock_enable(RCU_TIMER2);
    timer_oc_parameter_struct timer_ocintpara;
    timer_parameter_struct timer_initpara;

    /* TIMER1 configuration */
    timer_initpara.prescaler         = 9999;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 9999;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;

    /* TIMER2 configuration */
    timer_initpara.prescaler         = 9999;
    timer_initpara.period            = 999;
    timer_init(TIMER2,&timer_initpara);

        /* CH1 configuration in PWM mode0 */
    // timer_ocintpara.ocpolarity  = TIMER_OC_POLARITY_HIGH;
    // timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
    // timer_channel_output_config(TIMER2,TIMER_CH_1,&timer_ocintpara);

    // timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_1,99);
    // timer_channel_output_mode_config(TIMER2,TIMER_CH_1,TIMER_OC_MODE_PWM0);
    // timer_channel_output_shadow_config(TIMER2,TIMER_CH_1,TIMER_OC_SHADOW_DISABLE);

    // timer_interrupt_enable(TIMER2, TIMER_INT_CH1);
    timer_interrupt_enable(TIMER2, TIMER_INT_UP);
    timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_UP);
    // timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_CH1);
    // dbg_periph_enable(DBG_TIMER2_HOLD);
    nvic_irq_enable(TIMER2_IRQn, 1U, 0U);

    /* enable TIMER2 */
    timer_enable(TIMER2);
}


void USART_DMA_Init(void)
{
    dma_single_data_parameter_struct dma_init_struct;
	rcu_periph_clock_enable(RCU_DMA1);
    dma_deinit(DMA1, DMA_CH2);
    dma_init_struct.direction = DMA_PERIPH_TO_MEMORY;
    dma_init_struct.memory0_addr = (uint32_t)g_ringBuffer;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.number = 150;
    dma_init_struct.periph_addr = (uint32_t)&USART_DATA(USART0);
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_single_data_mode_init(DMA1, DMA_CH2, &dma_init_struct);
    /* configure DMA mode */
    dma_circulation_enable(DMA1, DMA_CH2);
//    dma_circulation_disable(DMA1, DMA_CH2);
    dma_channel_subperipheral_select(DMA1, DMA_CH2, DMA_SUBPERI4);
    /* enable DMA channel2 */
    dma_channel_enable(DMA1, DMA_CH2);
    usart_dma_receive_config(USART0, USART_DENR_ENABLE);
	
	dma_interrupt_enable(DMA1, DMA_CH2, DMA_CHXCTL_HTFIE);
	nvic_irq_enable(DMA1_Channel2_IRQn, 2U, 0U);
	
	usart_interrupt_enable(USART0, USART_INT_IDLE);
	nvic_irq_enable(USART0_IRQn, 2U, 0U);
}

uint8_t ModbusAnaly(uint8_t* i_buf, uint32_t numCounter)
{
	if(i_buf[0]!=0x01)
		return 0xFF;
	if(numCounter<5)
		return 0xFF;
	if(numCounter < i_buf[2]+5)
		return 1;
	else
	{
		if(GetCRC16(i_buf, i_buf[2]+3)==((i_buf[i_buf[2]+3]<<8)|i_buf[i_buf[2]+4]))
		{
			lvChange_pagemaingauge(i_buf[3]<<8|i_buf[4],
					i_buf[5]<<8|i_buf[6],
					i_buf[7]<<8|i_buf[8],
					i_buf[9]<<8|i_buf[10]);
		}
		return 0xFF;
	}
}

void USART0_IRQHandler()
{
	static uint32_t g_counter1=0;
    if (RESET != usart_flag_get(USART0, USART_FLAG_IDLE))
    {
        //清除usart标志位
        usart_flag_clear(USART0, USART_FLAG_IDLE);
        uint32_t receivedBytes = 150-dma_transfer_number_get(DMA1, DMA_CH2);
        //清除dma标志位
        if (RESET != dma_flag_get(DMA1, DMA_CH2, DMA_FLAG_FTF))
		{
			dma_flag_clear(DMA1, DMA_CH2, DMA_FLAG_FTF);
			usart_interrupt_disable(USART0, USART_INT_IDLE);
//            USART_DMA_Init();
		}
        else if (receivedBytes >= 120 
        || ModbusAnaly(g_ringBuffer, receivedBytes) == 0xFF)
        {
			usart_interrupt_disable(USART0, USART_INT_IDLE);
//            USART_DMA_Init();
        }

		delay_ms(1);
    }
}


void DMA1_Channel2_IRQHandler(void)
{
	dma_flag_clear(DMA1, DMA_CH2, DMA_FLAG_HTF);
}

void TIMER2_IRQHandler(void)
{
    if(timer_interrupt_flag_get(TIMER2, TIMER_INT_FLAG_UP)==SET)
    {
        adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);
        adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
        timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_UP);
    }
    if(timer_interrupt_flag_get(TIMER2, TIMER_INT_FLAG_CH1)==SET)
    {
        adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE);
        timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_CH1);
    }
}

void EXTI10_15_IRQHandler(void)
{
    uint16_t t_data = 0x44, t_x=0, t_y=0;
    char t_char[30] = "";

    if (RESET != exti_interrupt_flag_get(TAMPER_KEY_EXTI_LINE)) {
        gd_eval_led_toggle(LED2);
        // PRINTF_UART0("KEY:");
        // // ReadTPXYOver(&t_x, &t_y);
        // ReadTPXY(&t_x, &t_y);
        // sprintf(t_char, "x:%d\ty:%d\r\n", t_x, t_y);
        // PRINTF_UART0(t_char);

        adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
        // lvChange_sliderTest();
        exti_interrupt_flag_clear(TAMPER_KEY_EXTI_LINE);
    }
}

void EXTI3_IRQHandler(void)
{
    uint16_t t_data = 0x44, t_x=0, t_y=0;
    char t_char[30] = "";
    if (RESET != exti_interrupt_flag_get(EXTI_3)) {
        delay_ms(100);
        if(gpio_input_bit_get(GPIOI, GPIO_PIN_3)==RESET)
        {
            gd_eval_led_toggle(LED2);
            PRINTF_UART0("TCH:");
            ReadTPXYOver(&t_x, &t_y);
            sprintf(t_char, "x:%d\ty:%d\r\n", t_x, t_y);
            PRINTF_UART0(t_char);
        }
        // lvChange_sliderTest();
        exti_interrupt_flag_clear(EXTI_3);
    }
}

void ADC_IRQHandler(void)
{
    uint16_t i=0;
    char t_char[30] = "";
    static int s_counter=0;
    static uint16_t s_recorder[480];
    uint16_t *t_displaySize;
    
    // if(adc_interrupt_flag_get(ADC0, ADC_INT_FLAG_ROVF)==SET){
    //     PRINTF_UART0("ADC OVER");
    //     adc_disable(ADC0);
    // }
    if(adc_interrupt_flag_get(ADC0, ADC_INT_FLAG_EOC)==SET)
    {
        s_recorder[s_counter] = adc_regular_data_read(ADC0);
        adc_counter++;
        s_counter++;
        if(s_counter>=480){
            s_counter = 0;
            adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE);
            t_displaySize = EXT_BUFFER0_ADDR;
            memset((void *)EXT_BUFFER0_ADDR, 0, LCD_WIDTH * LCD_HEIGHT * LCD_FB_BYTE_PER_PIXEL * 2);
            for (i = 0; i < 480; i++)
                t_displaySize[s_recorder[i]*272/0xFFF*480 + i] = 0xAAAA;
        }
        // sprintf(t_char, "adc:%x\t%f\r\n", i, (float)i/0xFFF*3.3);
        // PRINTF_UART0(t_char);
        adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOC);
    }
}

static uint8_t g_tipString[8] = {0x01, 0x03, 0x00, 0x63, 0x00, 0x30};
void TIMER1_IRQHandler(void)
{
    char t_char[30] = "";

    //1-for adc example
    // sprintf(t_char, "ADC for one second:%d\r\n", adc_counter);
    // PRINTF_UART0(t_char);
    // adc_counter = 0;

    //2-for modbus
    
    static 	uint8_t t_counter=0;
    t_counter++;
    if(t_counter>=2){
    	uint16_t t = GetCRC16(g_tipString,6);
		USART_DMA_Init();
    	g_tipString[6] = t>>8;
    	g_tipString[7] = t&0xFF;
        PRINTF_UART0Len((char*)g_tipString, 8);
    }
    t_counter = t_counter%2;

    gd_eval_led_toggle(LED1);
    timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_UP);
}
